# TVSerieEpisodesScreen - This screen allows user to browse episodes of one season
# Copyright (C) 2007 Lauri Taimila
# 
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

__licence__ = "GPLv2"
__copyright__ = "2007, Lauri Taimila"
__author__ = "Lauri Taimila <lauri@taimila.com>"

import os
import gtk
import pango
import clutter

from frontend.user_event import UserEvent
from frontend.gui.screens.screen import Screen
from frontend.gui.transitions.transition import Transition

# Widgets
from frontend.gui.widgets.text_menu import TextMenu
from frontend.gui.widgets.scroll_area import ScrollArea
from frontend.gui.widgets.text_menu_item import TextMenuItem
from frontend.gui.widgets.list_indicator import ListIndicator
from frontend.gui.widgets.eyecandy_texture import EyeCandyTexture

# Video library
from frontend.medialibrary.videos import TVSeries
from frontend.medialibrary.videos import TVEpisode

class TVSerieEpisodesScreen(Screen):
    """
    TVSerieEpisodesScreen
    
    This screen contains list of all episodes of one specific season.
    """
    
    def __init__(self, ui, frontend, data):
        """
        Initialize screen
        
        @param frontend: FrontendClient object
        @param theme: Theme object
        @param data: List [ TVSerie object, Season number ]
        """
        self.group = clutter.Group()
        Screen.__init__(self, ui.STAGE_WIDTH, ui.STAGE_HEIGHT)
        
        self.ui = ui
        self.frontend = frontend
        self.theme = frontend.getTheme()
        self.serie = data[0]
        self.season = data[1]
        
        # Screen Title (Displayed at the bottom left corner) 
        screen_title = clutter.Label()
        screen_title.set_font_name(self.theme.getFont() + " " + str(self.ui.y(0.13)) + "px")
        screen_title.set_color(self.theme.getColor("screentitle"))
        screen_title.set_text(self.serie.get_title())
        screen_title.set_name("screen_title")
        screen_title.set_position(self.ui.x(0), self.ui.y(0.87))
        screen_title.show()
        self.group.add(screen_title)
        
        self._create_episode_menu()
        self._create_episode_info_box()
        
        #List indicator
        self.li = ListIndicator(0.2, 0.045, self.theme, ListIndicator.VERTICAL)
        self.li.set_position(self.ui.STAGE_WIDTH - self.li.get_width() - self.ui.x(0.06589),
                             self.ui.STAGE_HEIGHT - self.ui.y(0.1953))
        self.li.set_delimiter(" | ")
        self.li.show()
        self.li.set_maximum(self.episode_menu.get_number_of_items())
        self.li.set_current(1)
        self.group.add(self.li)
        
        self.group.show()
        ui.getStage().add(self.group)
        
    def _create_episode_menu(self):
        """
        Create a list of available seasons
        """
        self.episode_menu = TextMenu(self.theme, 
                                    self.frontend.get_configuration().show_effects())
        self.episode_menu.set_row_count(1)
        #self.episode_menu.set_visible_column_count(10)
        self.episode_menu.set_item_size(self.ui.x(0.4393), self.ui.y(0.0781))
        self.episode_menu.set_position(self.ui.x(0.4978), self.ui.y(0.1563))
        
        # Create menu items based on MusicLibrary
        episodes = self.serie.get_episodes_from_season(self.season)
        for episode in episodes:
            item = TextMenuItem(self.ui.x(0.4393), self.ui.y(0.0781), self.theme, str(episode.get_episode_number()) + ". " + episode.get_title())
            item.set_userdata(episode)
            self.episode_menu.add_actor(item)
                
        self.episode_menu.show()
        self.episode_menu.set_active(True)
        self.group.add(self.episode_menu)
    
    def _create_thumbnail_texture(self):
        """
        Create a thumbnail texture. This is called as menu is scrolled
        """
        try:
            self.thumb.hide()
            del self.thumb
        except:
            pass # No problem, this is just the first time we call this method
        
        # Thumbnail. Use cover art if thumbnail doesn't exist
        if(self.episode_menu.get_current_menuitem().get_userdata().get_thumbnail_url() is not None):
            pixbuf = gtk.gdk.pixbuf_new_from_file(self.episode_menu.get_current_menuitem().get_userdata().get_thumbnail_url())
            tw = self.ui.x(0.2928) #FIXME
            th = self.ui.y(0.2799)
            tx = self.ui.x(0.05)
            ty = self.ui.y(0.2)
        else:
            tw = self.ui.x(0.1098)
            th = self.ui.y(0.2799)
            tx = self.ui.x(0.20)
            ty = self.ui.y(0.15)
            if(self.serie.has_cover_art()):
                pixbuf = gtk.gdk.pixbuf_new_from_file(self.serie.get_cover_art_url())
            else:
                pixbuf = gtk.gdk.pixbuf_new_from_file(self.theme.getImage("default_movie_art"))

        self.thumb = EyeCandyTexture(pixbuf, tw, th)
        self.thumb.set_position(tx, ty)
        self.thumb.show()
        self.group.add(self.thumb)
      
    def _create_episode_info_box(self):
        """
        Create a texture that is displayed next to track list. This texture
        displays album cover art.
        """
        self._create_thumbnail_texture()
        
        # Title
        self.title = clutter.Label()
        self.title.set_text(self.episode_menu.get_current_menuitem().get_userdata().get_title())
        self.title.set_font_name(self.theme.getFont() + " bold " + str(self.ui.y(0.04)) + "px")
        self.title.set_color(self.theme.getColor("title"))
        self.title.set_line_wrap(False)
        self.title.set_ellipsize(pango.ELLIPSIZE_END)
        self.title.set_position(self.ui.x(0.05), self.ui.y(0.55))
        self.title.set_width(self.ui.x(0.4026))
        self.title.show()
        self.group.add(self.title)
        
        # Plot
        plot = clutter.Label()
        plot.set_text(self.episode_menu.get_current_menuitem().get_userdata().get_plot())
        plot.set_font_name(self.theme.getFont() + " " + str(self.ui.y(0.029)) + "px")
        plot.set_color(self.theme.getColor("subtitle"))
        plot.set_width(self.ui.x(0.4))
        
        self.scroll_area = ScrollArea(self.ui.x(0.4), self.ui.y(0.3516), self.theme)
        self.scroll_area.set_step_size(self.ui.y(0.03906))
        self.scroll_area.set_content(plot)
        self.scroll_area.set_position(self.ui.x(0.05), self.ui.y(0.63))
        self.scroll_area.show()
        self.group.add(self.scroll_area)
    
    def _update_episode_info_box(self, episode):
        """
        Update episode infobox
        @param episode: Display information from this episode
        """
        self._create_thumbnail_texture()
        self.title.set_text(episode.get_title())
        self.title.set_width(self.ui.x(0.4))
        
        plot = clutter.Label()
        plot.set_text(self.episode_menu.get_current_menuitem().get_userdata().get_plot())
        plot.set_font_name(self.theme.getFont() + " " + str(self.ui.y(0.029)) + "px")
        plot.set_color(self.theme.getColor("subtitle"))
        plot.set_width(self.ui.x(0.4))
        self.scroll_area.set_content(plot)
        
    def get_group(self):
        """
        Get all actors of the screen.
        @return clutter.Group 
        """
        return self.group

    def get_type(self):
        """Return screen type."""
        return Screen.NORMAL
    
    def get_name(self):
        """Return screen name (human readble)"""
        return "TVSerieEpisodesScreen"
    
    def handle_user_event(self, event):   
        """ 
        Handle screen specific user events
        @param event: UserEvent object
        """
        type = event.get_type()
        
        if type == UserEvent.NAVIGATE_UP:
            if self.episode_menu.is_active():
                self.episode_menu.move(self.episode_menu.UP)
                self.li.set_current(self.episode_menu.get_current_postition() + 1)
                self._update_episode_info_box(self.episode_menu.get_current_menuitem().get_userdata())
            else:
                self.scroll_area.scroll_up()
        
        elif type == UserEvent.NAVIGATE_DOWN:
            if self.episode_menu.is_active():
                self.episode_menu.move(self.episode_menu.DOWN)
                self.li.set_current(self.episode_menu.get_current_postition() + 1)
                self._update_episode_info_box(self.episode_menu.get_current_menuitem().get_userdata())
            else:
                self.scroll_area.scroll_down()
                
        elif type == UserEvent.NAVIGATE_RIGHT:
            self.episode_menu.set_active(True)
            self.scroll_area.set_active(False)
        
        elif type == UserEvent.NAVIGATE_LEFT:
            self.episode_menu.set_active(False)
            self.scroll_area.set_active(True)
        
        elif type == UserEvent.NAVIGATE_FIRST_PAGE:
            self.scroll_area.scroll_to_top()
        
        elif type == UserEvent.NAVIGATE_LAST_PAGE:
            self.scroll_area.scroll_to_bottom()
        
        elif type == UserEvent.NAVIGATE_PREVIOUS_PAGE:
            self.scroll_area.scroll_page_up()
        
        elif type == UserEvent.NAVIGATE_NEXT_PAGE:
            self.scroll_area.scroll_page_down()
            
        elif type == UserEvent.NAVIGATE_SELECT:
            episode = self.episode_menu.get_current_menuitem().get_userdata()
            mp = self.ui.get_media_player()
            mp.set_media(episode)
            mp.play()
            self.ui.changeScreen(self.ui.createScreen("video_osd"), Transition.FORWARD)